package br.com.furb.larcmsg.controller;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import br.com.furb.larcmsg.model.Mensagem;
import br.com.furb.larcmsg.model.Usuario;


public class Controller {

	private static final String SERVER = "larc.inf.furb.br";
	private static final int TCP_PORT = 1012;
	private static final int UDP_PORT = 1011;
	private static final String USER = "1228:wbmky";
	private static final Usuario SERVER_USER = new Usuario(0, "Servidor", 0);
	private static final String ENCODE = "UTF-8";
	private Map<Integer, Usuario> usuarios = null;
	
	public Map<Integer, Usuario> buscaUsuarios() throws UnknownHostException, IOException {
		
		Socket socket = new Socket(SERVER, TCP_PORT);

		try {
			PrintStream envio = new PrintStream(socket.getOutputStream()); 
			envio.print(String.format("GET USERS %s", USER));
			envio.flush();
			
			BufferedReader recebimento = new BufferedReader(new InputStreamReader(socket.getInputStream(),ENCODE));
			Map<Integer, Usuario> retorno = new HashMap<Integer, Usuario>();
			
			String usuarios = recebimento.readLine();
			Pattern pattern = Pattern.compile("\\d{4}:[\\p{L}|' ']+:\\d:");
			Matcher matcher = pattern.matcher(usuarios);
			
			while(matcher.find()) {
				Usuario usuario = Usuario.parse(matcher.group());
				retorno.put(usuario.getId(), usuario);
			}
		
			this.usuarios = retorno;
			
			return retorno;
		} finally {
			closeSocket(socket);
		}
		
	}
	
	public List<Mensagem> buscaMensagens() throws UnknownHostException, IOException {
		
		Socket socket = new Socket(SERVER, TCP_PORT);

		try {
			List<Mensagem> retorno = new LinkedList<Mensagem>();

			while(true) {
				PrintStream envio = new PrintStream(socket.getOutputStream()); 
				envio.print(String.format("GET MESSAGE %s", USER));
				envio.flush();
				
				BufferedReader recebimento = new BufferedReader(new InputStreamReader(socket.getInputStream(),ENCODE));
				String msgRecebimento = recebimento.readLine();
				
				if(msgRecebimento.equals(":")) {
					return retorno;
				} else {
					String[] partes = msgRecebimento.split(":");
					
					Mensagem mensagem = new Mensagem();
					
					if(partes[0].equals("0")) {
						mensagem.setUsuario(SERVER_USER);
					} else {
						mensagem.setUsuario(usuarios.get(Integer.parseInt(partes[0])));
					}
					
					mensagem.setTexto(partes[1]);
					
					retorno.add(mensagem);
				}
			}
		} finally {
			closeSocket(socket);
		}
		
	}
	
	public void enviarMensagem(String mensagem, Usuario usuario) throws UnknownHostException, IOException {
		String msgPacote = String.format("SEND MESSAGE %s:%d:%s", USER, usuario.getId(), mensagem);
		
		DatagramSocket dsocket = new DatagramSocket();
		
		try {
			DatagramPacket packet = new DatagramPacket(msgPacote.getBytes(), msgPacote.getBytes().length,
					InetAddress.getByName(SERVER), UDP_PORT);
			
			dsocket.send(packet);
		} finally {
			dsocket.close();
		}
	}
	
	public void enviarMensagemBroadcast(String mensagem) throws UnknownHostException, IOException {
		enviarMensagem(mensagem, SERVER_USER);
	}
	
	public void closeSocket(Socket socket) throws IOException {
		if(socket != null) {
			socket.close();
		}
	}

	public Collection<Usuario> getUsuarios() {
		return usuarios.values();
	}
}
